home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 018 / browser / menustack.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  7KB  |  231 lines

  1. /*
  2.  *  Simple menu package.  Needs lotsa work to handle some cases.
  3.  *
  4.  *  Copyright 1985
  5.  *  Louis A. Mamakos
  6.  *  Software & Stuff
  7.  *  14813 Ashford Place
  8.  *  Laurel, MD  20707
  9.  *
  10.  *  For non-commerical use only.  This program, or any modifications, may not
  11.  *  be sold or incorporated into any product without prior permission from the
  12.  *  author.
  13.  *
  14.  *  Modified by mwm to handle "stacking" menus.
  15.  *    NB - adding item to a menu that's been "popped" back to doesn't work,
  16.  *    and probably never will.
  17.  *     I took at the subitem code at the same time - mwm
  18.  */
  19.  
  20. /* Change if your terminal isn't * x 400 */
  21. #define SCREENHEIGHT        200
  22.  
  23. #include <exec/types.h>
  24. #include <exec/nodes.h>
  25. #include <exec/lists.h>
  26. #include <exec/ports.h>
  27. #include <exec/devices.h>
  28. #include <exec/memory.h>
  29. #include <hardware/blit.h>
  30. #include <graphics/copper.h>
  31. #include <graphics/regions.h>
  32. #include <graphics/rastport.h>
  33. #include <graphics/gfxbase.h>
  34. #include <graphics/gels.h>
  35. #include <intuition/intuition.h>
  36.  
  37. #define MNUM(menu,item,sub) (SHIFTMENU(menu)|SHIFTITEM(item)|SHIFTSUB(sub))
  38.  
  39. struct    Mem_Node {
  40.    struct Node mn_Node;
  41.    struct Remember mn_Memory;
  42.    struct Menu *mn_Menu;
  43.    } *Top, *RemHead();
  44.  
  45. static struct List Memory;
  46. static int Cur_Menu, Cur_MenuItem, Cur_SubItem;
  47. static struct Menu *LastMenu;
  48. static struct MenuItem *LastMenuItem;
  49.  
  50. struct Menu *AutoMenu;      /* menu struct being dynamically built */
  51.  
  52. char *strsave();        /* Save a string in the remember list */
  53.  
  54. Menu_Init()
  55. {
  56.    Memory.lh_Head = (struct Node *) &(Memory.lh_Tail);
  57.    Memory.lh_TailPred = (struct Node *) &(Memory.lh_Head);
  58.    Memory.lh_Tail = NULL;
  59.    Memory.lh_Type = NT_MEMORY;
  60.    Top = NULL;
  61.    Cur_Menu = Cur_MenuItem = -1;
  62.    AutoMenu = LastMenu = NULL;     /* no menu chain yet */
  63.    LastMenuItem = NULL;
  64. }
  65.  
  66. Menu_Clear()
  67. {
  68.  
  69.    while ((Top = RemHead(&Memory)) != NULL) {
  70.       FreeRemember(&(Top->mn_Memory), TRUE);
  71.       FreeMem(Top, sizeof(struct Mem_Node));
  72.   }
  73.   Menu_Init();            /* Just for safeties sake */
  74. }
  75.  
  76. Menu_Pop()
  77. {
  78.  
  79.    if ((Top = RemHead(&Memory)) == NULL) return NULL;
  80.    FreeRemember(&(Top->mn_Memory), TRUE);
  81.    FreeMem(Top, sizeof(struct Mem_Node));
  82.    /* Now, set Top back to the real list head */
  83.    Top = (struct Mem_Node *) Memory.lh_Head;
  84.    LastMenu = Top->mn_Menu;
  85.    LastMenuItem = NULL;        /* Wrong, but you can't add items here anyway */
  86.    Cur_Menu--;
  87. }
  88. /*
  89.  *  Add a MENU item.  Args are the text of the menu item, and an enable
  90.  *  flag.  Returns an Intuition type menu number, with the MenuItem and
  91.  *  Menu SubItem being NOITEM and NOSUB.  The MENUITEM part is valid.
  92.  */
  93. Menu_Add(name, enabled)
  94.    char *name;
  95.    int enabled;
  96. {
  97.    register struct Menu *m;
  98.  
  99.    if ((Top = (struct Mem_Node *) AllocMem(
  100.          sizeof(struct Mem_Node), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  101.       return NULL;
  102.    Top->mn_Node.ln_Type = NT_MEMORY;
  103.  
  104.    if ((m = (struct Menu *)AllocRemember(&(Top->mn_Memory),
  105.                  sizeof (struct Menu), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  106.       return NULL;
  107.    Top->mn_Menu = m;
  108.  
  109.    if (LastMenu == NULL)
  110.       AutoMenu = m;     /* first menu on list */
  111.    else
  112.       LastMenu->NextMenu = m;      /* link it in */
  113.  
  114.    LastMenuItem = NULL;            /* end of previous MenuItem list */
  115.    Cur_MenuItem = -1; /* reset item numbers */
  116.    if (LastMenu == NULL)
  117.       m->LeftEdge = 0;
  118.    else
  119.       m->LeftEdge = LastMenu->LeftEdge + LastMenu->Width;
  120.    m->TopEdge = 0;
  121.    m->Width = strlen(name) * 8;
  122.    Top->mn_Node.ln_Name = m->MenuName = strsave(name);
  123.    m->Height = 0;
  124.    m->Flags = enabled ? MENUENABLED : 0;
  125.    m->FirstItem = NULL;
  126.    LastMenu = m;
  127.  
  128.    AddHead(&Memory, Top);
  129.    return MNUM(++Cur_Menu, NOITEM, NOSUB);
  130. }
  131.  
  132. /*
  133.  *  Add a menu item to the current MENU.  Note that Add_Menu *must* be
  134.  *  called before this function.
  135.  */
  136. Menu_Item_Add(name, flags, mux, ch)
  137.    char *name;       /* name of menu item */
  138.    USHORT flags;
  139.    LONG mux;         /* mutual exclusion mask */
  140.    BYTE ch;        /* command sequence character, if COMMSEQ */
  141. {
  142.    register struct MenuItem *m, *n;
  143.    register struct IntuiText *it;
  144.  
  145.    flags &= CHECKIT|CHECKED|COMMSEQ|MENUTOGGLE|ITEMENABLED|HIGHCOMP|HIGHBOX;
  146.    if (LastMenu == NULL)
  147.       return MNUM(NOMENU, NOITEM, NOSUB);
  148.  
  149.    if ((m = (struct MenuItem *) AllocRemember(&(Top->mn_Memory),
  150.                  sizeof(struct MenuItem), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  151.       return MNUM(NOMENU, NOITEM, NOSUB);
  152.  
  153.    if (LastMenuItem == NULL)
  154.       LastMenu->FirstItem  = m;
  155.    else
  156.       LastMenuItem->NextItem = m;
  157.    m->Flags = flags | ITEMTEXT;
  158.    /*
  159.     *  Check for highlight mode:  if none selected, use HIGHCOMP
  160.     */
  161.    if ((m->Flags & (HIGHCOMP | HIGHBOX)) == 0)
  162.       m->Flags |= HIGHCOMP;
  163.    m->Command = ch;
  164.    m->MutualExclude = mux;
  165.    m->SubItem = NULL;
  166.    m->ItemFill = (APTR) AllocRemember(&(Top->mn_Memory),
  167.                       sizeof(struct IntuiText), MEMF_PUBLIC | MEMF_CLEAR);
  168.    it = (struct IntuiText *) m->ItemFill;
  169.    it->FrontPen = AUTOFRONTPEN;
  170.    it->BackPen = AUTOBACKPEN;
  171.    it->DrawMode = JAM2;
  172.    if (flags & CHECKIT)
  173.       it->LeftEdge = CHECKWIDTH + 1;
  174.    else
  175.       it->LeftEdge = 1;
  176.    it->TopEdge = 1;
  177.    it->ITextFont = NULL;      /* default font */
  178.    it->IText = strsave(name);
  179.    it->NextText = NULL;
  180.    m->Width = 0;
  181.    if (LastMenuItem == NULL) {
  182.       m->TopEdge = 2;
  183.       m->LeftEdge = 0;
  184.    } else if (LastMenuItem->TopEdge + 40 > SCREENHEIGHT) {
  185.       m->TopEdge = 2;
  186.       m->LeftEdge = LastMenuItem->LeftEdge + LastMenuItem->Width + 12;
  187.    } else {
  188.       m->TopEdge = LastMenuItem->TopEdge + 12;
  189.       m->LeftEdge = LastMenuItem->LeftEdge;
  190.    }
  191.    if (flags & CHECKIT)
  192.       m->Width += CHECKWIDTH;
  193.    if (flags & COMMSEQ)
  194.       m->Width += COMMWIDTH + 20;
  195.    m->Width += IntuiTextLength(m->ItemFill);
  196.    m->Height = 10;
  197.    /*
  198.     *  Check last menu item's width to see if it is larger than this
  199.     *  item's.  If new item is larger, then update width of all other
  200.     *  items.
  201.     */
  202.    if (LastMenuItem) {
  203.       if (LastMenuItem->Width > m->Width)
  204.         m->Width = LastMenuItem->Width;
  205.       else {
  206.          register short delta = m->Width - LastMenuItem->Width;
  207.  
  208.      for (n = LastMenu->FirstItem; n != m; n = n->NextItem) {
  209.         n->Width = m->Width;
  210.         if (n->LeftEdge > 0) n->LeftEdge += delta;
  211.      }
  212.      if (m->LeftEdge > 0) m->LeftEdge += delta;
  213.       }
  214.    }
  215.    LastMenuItem = m;
  216.    return MNUM(Cur_Menu, ++Cur_MenuItem, NOSUB);
  217. }
  218.  
  219.  
  220.  
  221. char *
  222. strsave(string) char *string; {
  223.    char *out ;
  224.  
  225.    out = (char *) AllocRemember(&(Top->mn_Memory), strlen(string) + 1,
  226.     MEMF_PUBLIC) ;
  227.    if (out == NULL) return NULL ;
  228.    (void) strcpy(out, string) ;
  229.    return out ;
  230. }
  231.